﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Syndication;
using MyClub.Model;
using MyClub.Web.Routing;
using System.Web.Routing;
using System.Globalization;
using System.Xml;
namespace MyClub.Web.Handlers
{
    /// <summary>
    /// Provides syndication of site posts as atom or rss feeds.
    /// </summary>
    public class PostFeed : IHttpHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PostFeed"/> class.
        /// </summary>
        public PostFeed()
        {
        }

        /// <summary>
        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        public void ProcessRequest(HttpContext context)
        {
            // Initialize parameters
            string path;
            if (this.IsRouted())
            {
                RequestContext requestContext = this.GetRequestContext();
                if (!requestContext.RouteData.Values.ContainsKey("CategoryPath"))
                    throw new InvalidOperationException();

                path = (string)requestContext.RouteData.Values["CategoryPath"];
            }
            else
            {
                path = context.Request["CategoryPath"];
            }

            context.Response.ContentType = "application/atom+xml";

            using (MyClubEntities entities = new MyClubEntities())
            {
                var categoryQuery = from c in entities.Category
                                    where string.Compare(c.Path, path, StringComparison.OrdinalIgnoreCase) == 0
                                    select c;

                var category = categoryQuery.First();

                IEnumerable<SyndicationItem> items = QueryPosts(context, entities, path);

                DateTimeOffset lastUpdatedTime;

                var newestItem = items.FirstOrDefault();
                if (newestItem != null)
                    lastUpdatedTime = newestItem.LastUpdatedTime;
                else
                    lastUpdatedTime = DateTimeOffset.Now;

                var feed = new SyndicationFeed(category.Title, category.Summary, PathToUrl(context, category.Path), category.Id.ToString("D", CultureInfo.InvariantCulture), lastUpdatedTime, items);

                var formatter = new Atom10FeedFormatter(feed);
                using (var xmlWriter = XmlWriter.Create(context.Response.OutputStream))
                    formatter.WriteTo(xmlWriter);
            }
        }

        private static IEnumerable<SyndicationItem> QueryPosts(HttpContext context, MyClubEntities entities, string path)
        {
            var postQuery = from p in entities.Post
                            where p.Path.StartsWith(path)
                            orderby p.ModificationDate descending
                            select p;

            List<SyndicationItem> items = new List<SyndicationItem>();
            foreach (var post in postQuery.Take(20))
            {
                var item = new SyndicationItem(
                                    post.Title,
                                    post.Summary,
                                    PathToUrl(context, post.Path),
                                    post.UniqueId.ToString("D", CultureInfo.InvariantCulture),
                                    new DateTimeOffset(post.ModificationDate));
                items.Add(item);
            }
            return items;
        }

        private static Uri PathToUrl(HttpContext context, string path)
        {
            return new Uri(context.Request.Url, context.Request.ApplicationPath.TrimEnd('/') + path);
        }

        /// <summary>
        /// Gets a value indicating whether another request can use the <see cref="T:System.Web.IHttpHandler"/> instance.
        /// </summary>
        /// <value></value>
        /// <returns>true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false.
        /// </returns>
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
